/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package mathma.core.vector;

import mathma.core.expr.Expression;

import mathma.core.form.FormulaicExpression;
import mathma.core.form.TypeConversionExpression;

import mathma.core.real.Integer;
import mathma.core.real.Real;

import mathma.core.value.Value;
import mathma.core.value.ValueType;

import java.util.ArrayList;
import java.util.List;

/**
 * @since 0.2.6
 * @author Ethan Levine
 */
public class VectorComponentExpression<E extends Value>
        extends FormulaicExpression<E, Vector<E>> {

    private final Expression<Vector<E>> operand;
    private final Expression<Real> comp;

    public VectorComponentExpression(ValueType<E> type,
            Expression<Vector<E>> operand, Expression<Real> component) {
        super(type);
        this.operand = operand;
        comp = component;
    }

    public E evaluate() {
        Real compValue = comp.evaluate();
        if (compValue.isInteger()) {
            return operand.evaluate().getComponent(compValue.intValue()).evaluate();
        } else {
            // TODO calculation exception - non-integer index
            throw new RuntimeException();
        }
    }

    public List<Expression<Vector<E>>> getOperands() {
        List<Expression<Vector<E>>> operands = new ArrayList<Expression<Vector<E>>>();
        operands.add(operand);
        operands.add(new TypeConversionExpression<Vector<E>, Real>(Vector.GenericType, comp));
        return operands;
    }

    public VectorComponentExpression<E> newInstance(List<Expression<Vector<E>>> operands) {
        if (operands.size() == 2 &&
                operands.get(1).getClass().equals(TypeConversionExpression.class) &&
                ((TypeConversionExpression) operands.get(1)).getOperand().getType().equals(Real.Type)) {
            return new VectorComponentExpression<E>(getType(), operands.get(0),
                    ((TypeConversionExpression<Vector<E>, Real>) operands.get(1)).getOperand());
        } else {
            throw new IllegalArgumentException(
                    "Invalid argument to VectorComponentExpression.newInstance.");
        }
    }
}
